﻿using System;
using System.Net;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
/// <summary>
/// 文件下载
/// </summary>
public class HTTPDownLoad
{
    // 下载进度
    public float Progress {
        get;
        private set;
    }
    // 状态 0 正在下载 1 下载完成 -1 下载出错
    public int Status {
        get;
        private set;
    }
    // 错误信息
    public string Error {
        get;
        set;
    }
    // 总长度
    public long TotalLength {
        get;
        private set;
    }
    // 保存路径
    private string savePath;
    // url地址
    private string url;
    // 超时时间
    private int timeout;
    // 子线程
    private Thread thread;
    // 子线程是否停止标志
    private bool isStop;
    // 下载时的回调
    private Action<int, float, string> callback;
    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="url">url地址</param>
    /// <param name="timeout">超时时间</param>
    /// <param name="callback">回调函数</param>
    public HTTPDownLoad (string url, string savePath, int timeout, Action<int, float, string> callback)
    {
        // Debug.Log("开启线程下载===" + savePath);
        this.savePath = savePath;
        this.url = url;
        this.timeout = timeout;
        this.callback = callback;
    }
    /// <summary>
    /// 开启下载
    /// </summary>
    public void DownLoad() {
        // Debug.Log("开启线程下载===");
        // 开启线程下载
        thread = new Thread (StartDownLoad);
        thread.IsBackground = true;
        thread.Start ();
    }
    /// <summary>
    /// 开始下载
    /// </summary>
    private void StartDownLoad() {
        try {
            // Debug.Log("构建文件流=== StartDownLoad");
            // 构建文件流
            FileStream fs = new FileStream (this.savePath, FileMode.OpenOrCreate, FileAccess.Write);
            // Debug.Log("文件当前长度===");
            // 文件当前长度
            long fileLength = fs.Length;
            // Debug.Log("构建文件流=== fileLength = " + fileLength);
            // 文件总长度
            TotalLength = GetDownLoadFileSize ();
            // Debug.LogFormat("fileLen:{0}", TotalLength);
            if (fileLength < TotalLength) {
                // 没有下载完成
                fs.Seek (fileLength, SeekOrigin.Begin);
                // 发送请求开始下载
                HttpWebRequest request = WebRequest.Create (this.url) as HttpWebRequest;
                request.AddRange ((int)fileLength);
                request.Timeout = this.timeout;
                // 读取文件内容
                Stream stream = request.GetResponse().GetResponseStream();
                if (stream.CanTimeout) {
                    stream.ReadTimeout = this.timeout;
                }
                byte[] buff = new byte[4096];
                int len = -1;
                while ((len = stream.Read (buff, 0, buff.Length)) > 0) {
                    if (isStop) {
                        break;
                    }
                    fs.Write (buff, 0, len);
                    fileLength += len;
                    Progress = fileLength * 1.0f / TotalLength;
                    this.callback(Status, Progress, "loading");
                } 
                stream.Close ();
                stream.Dispose ();
            } else {
                Progress = 1;
            }
            fs.Close ();
            fs.Dispose ();
            // 标记下载完成
            if (Progress == 1) {
                Status = 1;
                this.callback(Status, Progress, "success");
            }
        } catch (Exception e) {
            Debug.Log("插件更新失败");
            Error = e.Message;
            Status = -1;
            this.callback(Status, Progress, Error);
        }
    }
    /// <summary>
    /// 获取下载的文件大小
    /// </summary>
    /// <returns>文件大小</returns>
    public long GetDownLoadFileSize() {
        HttpWebRequest request = WebRequest.Create (this.url) as HttpWebRequest;
        request.Method = "HEAD";
        request.Timeout = this.timeout;
        HttpWebResponse response = request.GetResponse () as HttpWebResponse;
        return response.ContentLength;
    }
    /// <summary>
    /// 关闭下载
    /// </summary>
    public void Close() {
        this.isStop = true;
    }
}